﻿using System.Collections.Generic;
using System.ComponentModel;
using System.Windows;

using Microsoft.Practices.Composite.Events;
using Microsoft.Practices.Composite.Modularity;
using Microsoft.Practices.Composite.Presentation.Events;
using Microsoft.Practices.Composite.Regions;
using Microsoft.Practices.Unity;

using Matchingo.Common.Constants;
using Matchingo.Common.Types.Enumerations;
using Matchingo.Common.Types.Events;
using Matchingo.Common.Types.Interfaces;

namespace Matchingo.Modules.OptionsModule
{
    public class OptionsScreenViewModel : DependencyObject, IMenuItem, IModule, INotifyPropertyChanged
    {
        #region ========== Local Members ==========

        private readonly IUnityContainer Container;
        private readonly IRegionManager RegionManager;
        private readonly IMenuFlowProvider FlowProvider;
        private readonly IGameSettingsProvider SettingsProvider;
        private readonly IEventAggregator EventAggregator;
        private readonly ICardSetProvider CardSetProvider;
        private readonly IBackgroundSetProvider BackgroundSetProvider;

        private IOptionsScreenView View { get; set; }

        #endregion

        #region ========== Public Properties ==========

        public int CardCount
        {
            get { return SettingsProvider.GameSettings.CardCount; }
            set
            {
                SettingsProvider.GameSettings.CardCount = value;
                SettingsProvider.SaveSettings(); 
                NotifyPropertyChanged("CardCount");
            }
        }

		public double SoundVolume
		{
			get { return SettingsProvider.GameSettings.SoundVolume; }
			set
			{
				SettingsProvider.GameSettings.SoundVolume = value;
				SettingsProvider.SaveSettings();
				NotifyPropertyChanged("SoundVolume");
			}
		}

		public string SelectedCardSetName
		{
			get { return SettingsProvider.GameSettings.CardSetName; }
			set
			{
				SettingsProvider.GameSettings.CardSetName = value;
				SettingsProvider.SaveSettings();
				NotifyPropertyChanged("SelectedCardSetName");
			}
		}

		public string SelectedBackgroundSetName
		{
			get { return SettingsProvider.GameSettings.BackgroundSetName; }
			set
			{
				SettingsProvider.GameSettings.BackgroundSetName = value;
				SettingsProvider.SaveSettings();
				NotifyPropertyChanged("SelectedBackgroundSetName");
			}
		}

		public List<string> CardSetNames
		{
            get { return CardSetProvider.CardSetsAvailable; }
		}

		public List<string> BackgroundSetNames
		{
            get { return BackgroundSetProvider.BackgroundSetsAvailable; }
		}

        #endregion

        #region ========== Constructor ==========

        public OptionsScreenViewModel(IUnityContainer container, IRegionManager regionManager, 
            IEventAggregator eventAggregator, 
			IMenuFlowProvider flowProvider, IGameSettingsProvider settingsProvider, 
			ICardSetProvider cardSetProvider, IBackgroundSetProvider backgroundSetProvider)
        {
            Container = container;
			CardSetProvider = cardSetProvider;
			BackgroundSetProvider = backgroundSetProvider;
            SettingsProvider = settingsProvider;
            RegionManager = regionManager;
            FlowProvider = flowProvider;
			EventAggregator = eventAggregator;
        }

        #endregion

        #region ========== Public Methods ==========

        public void Initialize()
        {
            View = Container.Resolve<IOptionsScreenView>();
            View.Initialize(this);

            // register this UserControl with our UI Flow Provider
			FlowProvider.RegisterUIModule(this, MenuModuleNames.ModuleNames.OptionsMenu, View.RootElement);

            IRegion region = RegionManager.Regions[CommonConstants.SHELL_REGION_Options];
            region.Add(View);

			// TODO:: is this necessary?
            SettingsProvider.PropertyChanged += (s, e) => View.UpdateControlValues();
			EventAggregator.GetEvent<AvailableBackgroundSetsChangedEvent>().Subscribe(AvailableBackgroundSetsChanged, ThreadOption.UIThread);
			EventAggregator.GetEvent<AvailableCardSetsChangedEvent>().Subscribe(AvailableCardSetsChanged, ThreadOption.UIThread);
        }

        #endregion

        #region ========== Private Methods ==========

        private void NotifyPropertyChanged(string propertyName)
        {
            if (PropertyChanged == null)
                return;

            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }

        #endregion

		#region =========== Event Handlers ==========

        // NOTE:: events fired from EventAggregator must be public in Silveright
        public void AvailableBackgroundSetsChanged(object unused)
		{
			NotifyPropertyChanged("BackgroundSetNames");
		}

        // NOTE:: events fired from EventAggregator must be public in Silveright
		public void AvailableCardSetsChanged(object unused)
		{
			NotifyPropertyChanged("CardSetNames");
		}

		#endregion

		#region =========== Public Events ==========

		public event PropertyChangedEventHandler PropertyChanged;

        #endregion

        #region IMenuItem Members

        public bool TransitionMenu(InOutEnumeration.InOut inOrOut, DirectionNames.Direction direction, bool skipAnimation)
        {
            if (direction != DirectionNames.Direction.Left)
                return false;

            if (inOrOut == InOutEnumeration.InOut.In)
                View.ShowScreen(skipAnimation);
            else
                View.HideScreen(skipAnimation);

            return true;
        }

        #endregion
    }
}
